package com.ruibang.glass.portal.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.portal.constant.UserErrorCode;
import com.ruibang.glass.portal.domain.RoleMenuReq;
import com.ruibang.glass.portal.domain.RolePageParams;
import com.ruibang.glass.portal.domain.RoleParams;
import com.ruibang.glass.portal.entity.RoleEntity;
import com.ruibang.glass.portal.entity.RoleMenuEntity;
import com.ruibang.glass.portal.mapper.RoleMapper;
import com.ruibang.glass.portal.mapper.UserRoleMapper;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.pojo.PageResult;
import com.teaming.cloud.framework2.common.model.ResultBody;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class RoleService extends ServiceImpl<RoleMapper, RoleEntity> implements IService<RoleEntity> {

    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RedisSingleService redisService;

    /**
     * 获取角色列表
     */
    public ResultBody<PageResult<List<RoleEntity>>> getRoleList(RolePageParams params) {
        if (!Optional.ofNullable(params).isPresent()) {
            return ResultBody.fail(UserErrorCode.PARAM_ERROR.getCode(), UserErrorCode.PARAM_ERROR.getMsg());
        }

        try {
            final LambdaQueryWrapper<RoleEntity> lambda = new QueryWrapper<RoleEntity>().lambda();
            if (StringUtils.isNotBlank(params.getRoleName())) {
                lambda.like(RoleEntity::getRoleName, params.getRoleName());
            }
            final IPage<RoleEntity> page = this.page(new Page<>(params.getPageNo(), params.getPageSize()), lambda);
            PageResult<List<RoleEntity>> pageResult = new PageResult<>(page);

            return ResultBody.success(pageResult);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultBody.fail(UserErrorCode.PAGESELECT_ROLE_ERROE.getCode(), UserErrorCode.PAGESELECT_ROLE_ERROE.getMsg());
        }
    }

    /***
     * 获取所有角色
     * @param params
     * @return
     */
    public List<RoleEntity> queryAllRoles(RolePageParams params) {
        return baseMapper.getRoleList(params);
    }

    /**
     * 保存角色
     *
     * @param params
     * @return
     */
    @Transactional
    public ResultBody saveRole(RoleParams params) {
        //保存角色
        RoleEntity entity = new RoleEntity();
        entity.setDescription(params.getDescription());
        entity.setParentRoleId(params.getParentRoleId());
        entity.setRoleName(params.getRoleName());
        entity.setOrderNum(params.getOrderNum());
        entity.setLevel(params.getLevel());
        this.save(entity);
        //放入缓存
        redisService.hset(RedisKey.ROLE_GROUP_TYPE, entity.getRoleId(), entity.getRoleName());
        //保存角色与菜单关系
        Optional.ofNullable(params.getMenuIds()).ifPresent(a -> {
            a.forEach(m -> {
                RoleMenuEntity roleMenu = new RoleMenuEntity();
                roleMenu.setMenuId(m);
                roleMenu.setRoleId(entity.getRoleId());
                roleMenuService.saveRoleMenu(roleMenu);

            });
        });
        return ResultBody.success();
    }

    /**
     * 修改角色信息
     *
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultBody<Void> update(RoleParams params) {
        RoleEntity entity = this.getById(params.getRoleId());
        if (!Optional.ofNullable(entity).isPresent()) {
            return ResultBody.fail(UserErrorCode.NOT_EXISTS.getCode(), UserErrorCode.NOT_EXISTS.getMsg());
        }
        if (StringUtils.isBlank(params.getRoleId())) {
            return ResultBody.fail(UserErrorCode.ROLE_ID_IS_EMPTY.getCode(), UserErrorCode.ROLE_ID_IS_EMPTY.getMsg());
        }

        entity.setDescription(params.getDescription());
        entity.setRoleName(params.getRoleName());
        entity.setOrderNum(params.getOrderNum());
        this.updateById(entity);
        //放入缓存
        redisService.hset(RedisKey.ROLE_GROUP_TYPE, entity.getRoleId(), entity.getRoleName());

        //删除原有的角色菜单
        roleMenuService.delByRoleId(params.getRoleId());

        //保存角色与菜单关系
        if (CollectionUtils.isNotEmpty(params.getMenuIds())) {
            List<RoleMenuEntity> roleMenus = new ArrayList<>();
            for (String menuId : params.getMenuIds()) {
                RoleMenuEntity roleMenu = new RoleMenuEntity();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(entity.getRoleId());
                roleMenus.add(roleMenu);
            }

            roleMenuService.saveBatch(roleMenus);
        }

        return ResultBody.success();
    }

    /**
     * 更新角色用户
     *
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultBody modifyRoleMenu(RoleParams params) {
        RoleEntity entity = this.getById(params.getRoleId());
        if (!Optional.ofNullable(entity).isPresent()) {
            return ResultBody.fail(UserErrorCode.NOT_EXISTS.getCode(), UserErrorCode.NOT_EXISTS.getMsg());
        }

        //删除原有的角色菜单
        roleMenuService.delByRoleId(params.getRoleId());

        //保存角色与菜单关系
        if (CollectionUtils.isNotEmpty(params.getMenuIds())) {
            List<RoleMenuEntity> roleMenus = new ArrayList<>();
            for (String menuId : params.getMenuIds()) {
                RoleMenuEntity roleMenu = new RoleMenuEntity();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(entity.getRoleId());
                roleMenus.add(roleMenu);
            }

            roleMenuService.saveBatch(roleMenus);
        }

        return ResultBody.success();
    }


    /**
     * 删除角色
     *
     * @param roleId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultBody<Void> remove(String roleId) {
        if (roleId == null) {
            return ResultBody.fail(UserErrorCode.PARAM_ERROR.getCode(), UserErrorCode.PARAM_ERROR.getMsg());
        }
        this.removeById(roleId);
        userRoleMapper.delByRoleId(roleId);
        roleMenuService.delByRoleId(roleId);
        //删除缓存
        redisService.hdel(RedisKey.ROLE_GROUP_TYPE, roleId);
        return ResultBody.success();
    }


    public ResultBody<List<String>> getRolesByUserId(String userId) {
        return ResultBody.success(userRoleMapper.getRolesByUserId(userId));
    }

    public List<String> getUserIdsByRoleIds(List<String> roleIds) {
        return userRoleMapper.getUserIdsByRoleIds(roleIds);
    }

    public List<RoleEntity> getRoleByMenuId(String menuId) {
        List<String> roleIds = roleMenuService.getRoleByMenuId(menuId);
        return this.listByIds(roleIds);
    }

    @Transactional(rollbackFor = Exception.class)
    public void editRoleMenu(RoleMenuReq roleMenuReq) {
        if (roleMenuReq != null) {
            //根据菜单id删除管关联信息
            roleMenuService.delByMenuId(roleMenuReq.getMenuId());
            //保存关联信息
            List<RoleMenuEntity> data = new ArrayList<>();
            for (String roleId : roleMenuReq.getRoleIds()) {
                RoleMenuEntity roleMenuEntity = new RoleMenuEntity();
                roleMenuEntity.setRoleId(roleId);
                roleMenuEntity.setMenuId(roleMenuReq.getMenuId());
                data.add(roleMenuEntity);
            }
            roleMenuService.saveBatch(data);
        }
    }
}
